package org.mqtt;

import lombok.Getter;
import org.algorithm.AES;

import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class MqttCiphertextHandler implements Serializable {

    private String deviceSecret;

    private String deviceId;

    private String mqttPassword;

    @Getter
    private CipherConfig cipherConfig;

    private byte[] iv;

    private byte[] secret;

    private byte[] deviceRandomSecret;

    @Getter
    private String clientId;

    private boolean inited = false;

    private boolean reinited = false;


    public void setDeviceSecret(String deviceSecret) {
        this.deviceSecret = deviceSecret;
        init();
    }

    public boolean getReInit(){
        return reinited;
    }

    public void reInit() {
        //根据加密方案初始化服务器端随机数加密密钥
        if (EncryptMethod.AES_SERVER_RANDOM.getCode().equals(cipherConfig.getEncryptMethod())) {
            String secretStr = deviceSecret + cipherConfig.getServerRandom();
            byte[] deviceSecretByte = secretStr.getBytes(StandardCharsets.UTF_8);
            secret = Arrays.copyOf(deviceSecretByte, 32);
        } else if (EncryptMethod.AES_DEVICE_RANDOM.getCode().equals(cipherConfig.getEncryptMethod())) {
            secret = deviceRandomSecret;
        }

        reinited = true;
    }

    private void init() {
        //初始化设备端随机数加密密钥
        String deviceRandomSecretStr = deviceSecret + cipherConfig.getRandom();
        byte[] deviceRandomSecretByte = deviceRandomSecretStr.getBytes(StandardCharsets.UTF_8);
        deviceRandomSecret = Arrays.copyOf(deviceRandomSecretByte, 32);
        secret = deviceRandomSecret;
        byte[] deviceIdByte = deviceId.getBytes(StandardCharsets.UTF_8);
        iv = Arrays.copyOf(deviceIdByte, 16);
        inited = true;
    }

    public MqttCiphertextHandler(String clientId, String username, String password) {
        this.clientId = clientId;
        this.deviceId = username;
        this.mqttPassword = password;
        if (clientId.matches(CipherConfig.AES_CODER_USERNAME)) {
            this.cipherConfig = new CipherConfig(clientId);
        }
    }

    public byte[] encryptRandom() throws Exception {
        if (inited) {
            return AES.encrypt(cipherConfig.getServerRandom().getBytes(StandardCharsets.UTF_8), deviceRandomSecret, iv);
        } else {
            throw new Exception("未初始化加密工具");
        }
    }

    public byte[] encrypt(byte[] data) throws Exception {
        if (inited) {
            return AES.encrypt(data, secret, iv);
        } else {
            throw new Exception("未初始化加密工具");
        }
    }

    public byte[] decrypt(byte[] encryptData) throws Exception {
        if (inited) {
            return AES.decrypt(encryptData, secret, iv);
        } else {
            throw new Exception("未初始化加密工具");
        }
    }
}
